package com.ruoyi.common.utils.html;

import com.ruoyi.common.utils.StringUtils;

/**
 * 转义和反转义工具类
 * 
 * @author ruoyi
 */
public class EscapeUtil{
	public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";

	private static final char[][] TEXT = new char[64][];

	static{
		for(int i = 0; i < 64; i++){
			TEXT[i] = new char[]{(char)i};
		}

		// special HTML characters
		TEXT['\''] = "&#039;".toCharArray(); // 单引号
		TEXT['"'] = "&#34;".toCharArray(); // 单引号
		TEXT['&'] = "&#38;".toCharArray(); // &符
		TEXT['<'] = "&#60;".toCharArray(); // 小于号
		TEXT['>'] = "&#62;".toCharArray(); // 大于号
	}

	/**
	 * 转义文本中的HTML字符为安全的字符
	 * 
	 * @param text 被转义的文本
	 * @return 转义后的文本
	 */
	public static String escape(String text){
		return encode(text);
	}

	/**
	 * 还原被转义的HTML特殊字符
	 * 
	 * @param content 包含转义符的HTML内容
	 * @return 转换后的字符串
	 */
	public static String unescape(String content){
		return decode(content);
	}

	/**
	 * 清除所有HTML标签，但是不删除标签内的内容
	 * 
	 * @param content 文本
	 * @return 清除标签后的文本
	 */
	public static String clean(String content){
		return new HTMLFilter().filter(content);
	}

	/**
	 * Escape编码
	 * 
	 * @param text 被编码的文本
	 * @return 编码后的字符
	 */
	private static String encode(String text){
		int len;
		if((text == null) || ((len = text.length()) == 0)){
			return StringUtils.EMPTY;
		}
		StringBuilder buffer = new StringBuilder(len + (len >> 2));
		char c;
		for(int i = 0; i < len; i++){
			c = text.charAt(i);
			if(c < 64){
				buffer.append(TEXT[c]);
			}else{
				buffer.append(c);
			}
		}
		return buffer.toString();
	}

	/**
	 * Escape解码
	 * 
	 * @param content 被转义的内容
	 * @return 解码后的字符串
	 */
	public static String decode(String content){
		if(StringUtils.isEmpty(content)){
			return content;
		}

		StringBuilder tmp = new StringBuilder(content.length());
		int lastPos = 0, pos = 0;
		char ch;
		while(lastPos < content.length()){
			pos = content.indexOf("%", lastPos);
			if(pos == lastPos){
				if(content.charAt(pos + 1) == 'u'){
					ch = (char)Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
					tmp.append(ch);
					lastPos = pos + 6;
				}else{
					ch = (char)Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
					tmp.append(ch);
					lastPos = pos + 3;
				}
			}else{
				if(pos == -1){
					tmp.append(content.substring(lastPos));
					lastPos = content.length();
				}else{
					tmp.append(content.substring(lastPos, pos));
					lastPos = pos;
				}
			}
		}
		return tmp.toString();
	}

	public static void main(String[] args){
		String html = "<script>alert(1);</script>";
		// String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
		// String html = "<123";
		System.out.println(EscapeUtil.clean(html));
		System.out.println(EscapeUtil.escape(html));
		System.out.println(EscapeUtil.unescape(html));
	}
}
